package com.linkoog.devtools.dubbo.raw_index;

import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.linkoog.devtools.dubbo.parser.DubboService;
import com.linkoog.devtools.dubbo.parser.DubboServiceParser;
import com.linkoog.devtools.metadata.raw_index.MethodMetadataRawFileIndex;
import com.linkoog.devtools.metadata.raw_index.MethodMetadata;
import com.linkoog.devtools.raw_index.core.PsiMethodRawFileIndex;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Set;

public class DubboMethodRawFileIndex extends PsiMethodRawFileIndex<DubboMethod> {


    public static final Key<Set<PsiElement>> key = Key.create("DevTools.DubboMethodRawFileIndex.Key");

    public DubboMethodRawFileIndex(Project project) {
    }

    public static DubboMethodRawFileIndex getInstance(Project project){
        return EXTENSION_POINT_NAME.findExtension(DubboMethodRawFileIndex.class, project);
    }

    @Override
    public Key<Set<PsiElement>> getPsiElementKey() {
        return key;
    }

    @Override
    public boolean isLasy() {
        return false;
    }

    @Override
    public File getCacheFile(Project project) throws IOException {
        return new File(project.getBasePath() + "/.idea/index-data/DubboMethod.idx");
    }

    @Override
    public Class<DubboMethod> getValueClass(Project project) {
        return DubboMethod.class;
    }

    @Override
    public DubboMethod resolve(PsiMethod psiMethod) {
        if (psiMethod == null) return null;
        if (!isInit()) return null;

        PsiClass psiClass = psiMethod.getContainingClass();
        if (psiClass == null || psiClass.getQualifiedName() == null) return null;

        final List<DubboServiceParser> extensionList = DubboServiceParser.EXTENSION_POINT_NAME.getExtensionList();
        if (extensionList.isEmpty()) return null;

        DubboService dubboService = extensionList.stream().map(dubboServiceParser -> dubboServiceParser.parse(psiClass)).filter(Objects::nonNull).findFirst().orElse(null);
        if (dubboService == null) return null;

        MethodMetadata methodMetadata =  MethodMetadataRawFileIndex.getInstance(project).getCache(psiMethod);
        if (methodMetadata == null) return null;

        String version = dubboService.getVersion();
        if (version == null || version.startsWith("${")) version = "";

        final VirtualFile virtualFile = psiMethod.getContainingFile().getOriginalFile().getVirtualFile();
        final long timestamp = virtualFile.getModificationStamp();
        DubboMethod dubboMethod = new DubboMethod(
                virtualFile.getUrl(), psiMethod.getTextOffset(), psiMethod.getName(),
                methodMetadata.getParamTypes(), methodMetadata.getReturnType(), psiClass.getQualifiedName(),
                dubboService.getSourceType(), dubboService.getInface(),
                version, dubboService.getGroup()
        );
        dubboMethod.initPsiElement(psiMethod.getProject(), psiMethod);
        dubboMethod.setJavaDoc(methodMetadata.getJavaDoc());
        dubboMethod.setSwaggerComment(methodMetadata.getSwaggerComment());
        dubboMethod.setTimestamp(timestamp);
        return dubboMethod;
    }
}
